# Less plugin

import { SourceCode } from '@rspress/core/theme';

<SourceCode href="https://github.com/web-infra-dev/rsbuild/tree/main/packages/plugin-less" />

Use [Less](https://lesscss.org/) as the CSS preprocessor, implemented based on [less-loader](https://github.com/webpack/less-loader).

## Quick start

### Install plugin

You can install the plugin using the following command:

import { PackageManagerTabs } from '@theme';

<PackageManagerTabs command="add @rsbuild/plugin-less -D" />

:::tip

- The Less plugin only supports @rsbuild/core versions >= 0.7.0.
- If the @rsbuild/core version is lower than 0.7.0, it has built-in support for the Less plugin, you do not need to install it.

:::

### Register plugin

You can register the plugin in the `rsbuild.config.ts` file:

```ts title="rsbuild.config.ts"
import { pluginLess } from '@rsbuild/plugin-less';

export default {
  plugins: [pluginLess()],
};
```

After registering the plugin, you can import `*.less` or `*.module.less` files into the code without adding other configs.

## Options

To customize the compilation behavior of Less, use the following options.

### lessLoaderOptions

You can modify the config of [less-loader](https://github.com/webpack/less-loader) via `lessLoaderOptions`.

- **Type:** `Object | Function`
- **Default:**

```js
const defaultOptions = {
  lessOptions: {
    javascriptEnabled: true,
    paths: [path.join(rootPath, 'node_modules')],
  },
  implementation: require.resolve('less'),
  sourceMap: rsbuildConfig.output.sourceMap.css,
};
```

- **Example:**

If `lessLoaderOptions` is an object, it is merged with the default config through `Object.assign` in a shallow way. It should be noted that `lessOptions` is merged through deepMerge in a deep way.

```js
pluginLess({
  lessLoaderOptions: {
    lessOptions: {
      javascriptEnabled: false,
    },
  },
});
```

If `lessLoaderOptions` is a function, the default config is passed as the first parameter, which can be directly modified or returned as the final result.

```js
pluginLess({
  lessLoaderOptions(config) {
    config.lessOptions = {
      javascriptEnabled: false,
    };
  },
});
```

:::tip
The `lessLoaderOptions.lessOptions` config is passed to Less. See the [Less documentation](https://lesscss.org/usage/#command-line-usage-options) for all available options.
:::

### include

- **Type:** [RuleSetCondition](https://rspack.rs/config/module#condition)
- **Default:** `/\.less$/`
- **Version:** `>= 1.1.0`

Include some `.less` files, they will be transformed by `less-loader`. The value is the same as the `rule.test` option in Rspack.

For example:

```ts
pluginLess({
  include: /\.custom\.less$/,
});
```

### exclude

- **Type:** [RuleSetCondition](https://rspack.rs/config/module#condition)
- **Default:** `undefined`

Exclude some `.less` files, they will not be transformed by `less-loader`.

For example:

```ts
pluginLess({
  exclude: /some-folder[\\/]foo\.less/,
});
```

### parallel

- **Type:** `boolean`
- **Default:** `false`
- **Version:** Added in v1.4.0

Whether to enable parallel loader execution, running `less-loader` in worker threads. When enabled, this typically improves build performance when compiling large numbers of Less modules.

Note that this option is experimental and may not work if your Less options contain functions.

```ts
pluginLess({
  parallel: true,
});
```

> See [Rspack - Rule.use.parallel](https://rspack.rs/config/module#ruleuseparallel) for more details.

## Modifying Less version

In some scenarios, if you need to use a specific version of Less instead of the built-in Less v4 in Rsbuild, you can install the desired Less version in your project and set it up using the `implementation` option of the `less-loader`.

```js
pluginLess({
  lessLoaderOptions: {
    implementation: require('less'),
  },
});
```

## Practices

### Configure multiple Less plugins

By using the `include` and `exclude` options, you can register multiple Less plugins and specify different options for each plugin.

For example:

```ts
export default {
  plugins: [
    pluginLess({
      exclude: /\.another\.less$/,
    }),
    pluginLess({
      include: /\.another\.less$/,
      lessLoaderOptions: {
        // some custom options
      },
    }),
  ],
};
```

## FAQ

### Division in Less file does not work?

The built-in Less version for `@rsbuild/plugin-less` is v4. Compared to v3, there are some differences in the division syntax in Less v4:

```less
// Less v3
.math {
  width: 2px / 2; // 1px
  width: 2px ./ 2; // 1px
  width: (2px / 2); // 1px
}

// Less v4
.math {
  width: 2px / 2; // 2px / 2
  width: 2px ./ 2; // 1px
  width: (2px / 2); // 1px
}
```

The division syntax in Less can be modified through configuration. For more details, see [Less - Math](https://lesscss.org/usage/#less-options-math).
